package cn.agiledata.bank.transaction.service;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;

import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.DateUtil;
import cn.agiledata.bank.common.util.StringUtil;
import cn.agiledata.bank.hibernateBean.Account;
import cn.agiledata.bank.hibernateBean.FeeRatio;
import cn.agiledata.bank.hibernateBean.FeeRatioHis;
import cn.agiledata.bank.hibernateBean.Groups;
import cn.agiledata.bank.hibernateBean.SubAccount;
import cn.agiledata.bank.hibernateBean.Transaction;
import cn.agiledata.bank.myspace.service.IMySpaceService;
import com.vnv.infrastructure.logic.IPBHibernate3BaseMgr;
import com.vnv.infrastructure.logic.IPBMgrFactory;

public class FeeForVNV extends IPBHibernate3BaseMgr implements FeeRatioInterf {
	private IMySpaceService mySpaceService;

	public IMySpaceService getMySpaceService() {
		return mySpaceService;
	}

	/**
	 * 
	 * @param transType
	 * @return
	 */
	public String getBuyOrSale(String transType, String flag) {

		// 线下银行汇款
		if (transType.equals(Constant.ACTION_TYPE_B)) {
			if (Constant.DEBIT_CREDIT_RECEIVE.equals(flag)) {
				flag = "N";
			}
		} else if (!transType.equals(Constant.ACTION_TYPE_C)) {
			flag = "N";
		}
		return flag;
	}

	public Long getDebitRatioHis(Transaction tran) {
		Long frh = getFeeRatio(tran, Constant.DEBIT_CREDIT_BUY);
		return frh;
	}

	public Long getCreditRatioHis(Transaction tran) {
		return getFeeRatio(tran, Constant.DEBIT_CREDIT_RECEIVE);
	}

	public FeeRatio getFeRatio(Groups ag, String id) {

		return getFeeRatio(getGradeId(ag), id, Constant.DEBIT_CREDIT_BUY,
				new Date(), "");
	}

	private Long getFeeRatio(Transaction tran, String buyOrsale) {
		FeeRatio fr;
		String bankSeq = "0";
		if (tran.getBankSeq() != null) {
			bankSeq = tran.getBankSeq().toString();
		}

		if (buyOrsale.equals(Constant.DEBIT_CREDIT_BUY)) {
			if (tran.getActionType().getId().toString().equals(
					Constant.ACTION_TYPE_J)) {
				fr = getFeeRatio(getGradeId(mySpaceService.getGroupByAccount(
						tran.getDebit().getAccount(), Constant.GROUP_TYPE_B)),
						tran.getActionType().getId().toString(), buyOrsale,
						tran.getBeginDate(), bankSeq);
			} else {
				fr = getFeeRatio(getGradeId(mySpaceService.getGroupByAccount(
						tran.getDebit().getAccount(), Constant.GROUP_TYPE_A)),
						tran.getActionType().getId().toString(), buyOrsale,
						tran.getBeginDate(), bankSeq);
			}
		} else {
			fr = getFeeRatio(getGradeId(mySpaceService.getGroupByAccount(tran
					.getCredit().getAccount(), Constant.GROUP_TYPE_A)), tran
					.getActionType().getId().toString(), buyOrsale, tran
					.getBeginDate(), bankSeq);
		}
		Long feeRatioId = fr == null ? null : fr.getId();
		List feeList = null;
		if (feeRatioId != null)
			feeList = getHibernateTemplate().find(
					"from FeeRatioHis s where s.id = ?",
					new Object[] { feeRatioId });
		// 获得收费费率
		Long frh = new Long(0);
		if (feeList != null && feeList.size() > 0)
			frh = ((FeeRatioHis) feeList.get(0)).getId();
		return frh;
	}

	private FeeRatioEncap fre;

	public void setFre(FeeRatioEncap fre) {
		this.fre = fre;
	}

	public double getCreditFee(Transaction tran) {
		String bankSeq = tran.getBankSeq() == null ? null : tran.getBankSeq()
				.toString();
		return getCreditFee(bankSeq, tran.getCredit().getAccount(), tran
				.getActionType().getId().toString(), tran.getAmount());
	}

	public double getCreditFee(String tranBankSeq, Account creditAccount,
			String actionType, Double amout) {
		if (tranBankSeq == null) {
			tranBankSeq = "0";
		}
		double fee = this.getFeeRate(getGradeId(mySpaceService
				.getGroupByAccount(creditAccount, Constant.GROUP_TYPE_A)),
				actionType, Constant.DEBIT_CREDIT_RECEIVE, new Date(), amout,
				tranBankSeq);
		return fee;
	}

	public double getDebitFee(SubAccount debit, String actionType,
			Double amount, String bankSeq) {
		return this.getFeeRate(getGradeId(mySpaceService.getGroupByAccount(
				debit.getAccount(), Constant.GROUP_TYPE_A)), actionType,
				Constant.DEBIT_CREDIT_BUY, new Date(), amount, bankSeq);
	}

	private String getGradeId(Groups ag) {
		if (ag.getId() != null) {
			return ag.getId().toString();
		} else {
			return null;
		}
	}

	public double getDebitFee(Transaction tran) {
		String bankSeq = "0";
		if (tran.getBankSeq() != null)
			bankSeq = tran.getBankSeq().toString();
		return this.getFeeRate(getGradeId(mySpaceService.getGroupByAccount(tran
				.getDebit().getAccount(), Constant.GROUP_TYPE_A)), tran
				.getActionType().getId().toString(), Constant.DEBIT_CREDIT_BUY,
				new Date(), tran.getAmount(), bankSeq);
	}

	/**
	 * 获取费率
	 * 
	 * @param groupId
	 *            客户类型ID （AccountGrade）
	 * @param transType
	 *            交易类型Id (ActionType)
	 * @param flag
	 *            买卖标志位 (SysBook) C or D
	 * @param transDate
	 *            交易日期
	 * @param transAmt
	 *            交易金额
	 * @return 如果数据库中存在，则返回费率值，否则返回null
	 */
	private double getFeeRate(String groupId, String transType, String flag,
			Date transDate, Double transAmt, String bank) {
		double ret = 0;
		boolean amFlag = false;

		if (transAmt.compareTo(new Double(0)) < 0) {
			amFlag = true;
			transAmt = new Double(-transAmt.doubleValue());
		}

		if (!StringUtil.isStrEmpty(groupId))

		{
			FeeRatio feeRatio = getFeeRatio(groupId, transType, flag,
					transDate, bank);
			if (feeRatio == null) {
			} else {
				// 费率取用的模式：1固定2比例
				if (feeRatio.getFeemethod().equals("1")) {
					ret = feeRatio.getFixFee().doubleValue();
				} else {
					ret = feeRatio.getRatio().doubleValue()
							* transAmt.doubleValue() / 100;
					// 费率的上限和下限
					if (ret < feeRatio.getMinFee().doubleValue())
						ret = feeRatio.getMinFee().doubleValue();

					// zln 修正 20080326 费率上限可以为空
					if (feeRatio.getMaxFee() != null
							&& feeRatio.getMaxFee().doubleValue() > 0) {
						// 费率上线为空时费率无上限
						if (ret > feeRatio.getMaxFee().doubleValue())
							ret = feeRatio.getMaxFee().doubleValue();
					}
				}
			}
			if (amFlag) {
				ret = -ret;
			}
		}

		// zln 修正 2008-3-24 修改手续费四舍五入保留小数后2位
		ret = new BigDecimal(ret).setScale(2, BigDecimal.ROUND_HALF_UP)
				.doubleValue();

		return ret;
	}

	/**
	 * 获取费率对象
	 * 
	 * @param groupId
	 *            客户类型ID （AccountGrade）
	 * @param transType
	 *            交易类型Id (ActionType)
	 * @param flag
	 *            买卖标志位 (SysBook) C or D
	 * @param transDate
	 *            交易日期
	 * @return 如果数据库中存在，则返回费率对象，否则返回null
	 */
	private FeeRatio getFeeRatio(String groupId, String transType, String flag,
			Date transDate, String bank) {
		FeeRatio feeRatio = null;
		List ls = null;
		String f = flag;
		if (groupId != null) {
			flag = getBuyOrSale(transType, flag);
			if (groupId.equals("1") && transType.equals(Constant.ACTION_TYPE_A)
					&& f.equals("D")) {
				String dateStr = " to_date(' "
						+ DateUtil.date2String(transDate)
						+ " 00:00:00','YYYY-MM-DD HH24:MI:SS')";
				StringBuffer clause = new StringBuffer(
						"  from FeeRatio fr where ");

				if (!StringUtil.isStrEmpty(bank))
					clause.append(" fr.relatingId = ").append(bank);

				clause.append(" and fr.relatingType = 3");
				clause.append(" and fr.beginDate <= ").append(dateStr);
				clause.append(" and fr.endDate >= ").append(dateStr);
				ls = getHibernateTemplate().find(clause.toString());
			} else {
				String dateStr = " to_date(' "
						+ DateUtil.date2String(transDate)
						+ " 00:00:00','YYYY-MM-DD HH24:MI:SS')";

				StringBuffer clause = new StringBuffer(
						"  from FeeRatio fr where ");

				clause.append(" (fr.relatingId = ").append(groupId);
				clause.append(" or fr.relatingId = -1)");
				clause.append(" and fr.actionType = ").append(transType);
				clause.append(" and fr.flag = '").append(flag).append("'");
				clause.append(" and fr.beginDate <= ").append(dateStr);
				clause.append(" and fr.endDate >= ").append(dateStr);

				ls = getHibernateTemplate().find(clause.toString());

				// 找不到费率
				if (ls == null)
					return feeRatio;

				// 从组开始查询费率，找不到往上一级找
				for (int i = 0, s = ls.size(); i < s; i++) {

					feeRatio = (FeeRatio) ls.get(i);
					if (!feeRatio.getRelatingId().equals("-1"))
						break;
				}
			}
		}

		return feeRatio;
	}

	public String getFeeRatio(Groups ag, String id) {
		FeeForVNV ff = (FeeForVNV) IPBMgrFactory.getMgr("FeeRatio");
		String rt;
		String fl;
		String str;

		FeeRatio fr = ff.getFeRatio(ag, id);
		if (fr == null) {
			return "优惠期间，免收手续费！";
		}
		String bDate = DateFormat.getDateInstance().format(fr.getBeginDate());
		String eDate = DateFormat.getDateInstance().format(fr.getEndDate());

		if (fr.getFeemethod().equals("1")) {
			rt = "固定收费";
			fl = fr.getFixFee().toString();
			str = ("收费方式：" + rt + " 手续费: " + fl + "元  有效期：" + bDate + " 至 " + eDate);
		} else {
			rt = "按金额比例";
			fl = fr.getRatio().toString() + "%";
			str = "收费方式：" + rt + " 费率: " + fl + " 最低收费：" + fr.getMinFee()
					+ "元  ";

			// zln 修正 20080326 费率上限可以为空
			if (fr.getMaxFee() != null && fr.getMaxFee().doubleValue() > 0) {
				str += "最高收费：" + fr.getMaxFee() + "元 ";
			}

			str += "有效期：" + bDate + " 至 " + eDate;
		}
		return str;
	}

	public void setMySpaceService(IMySpaceService mySpaceService) {
		this.mySpaceService = mySpaceService;
	}
}
